package config

import (
	"fmt"
	"github.com/unknwon/goconfig"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"
)

var (
	Config      *goconfig.ConfigFile
	Root        string
	cfgRoot     string
	TemplateDir string  //所有模版文件的目录，默认为:template
)

const initPath = "/config/config.ini"

func init() {
	fileName := os.Args[0]                  //获取终端输入的第一个参数的值
	exePath, err := exec.LookPath(fileName) //在当前环境中查找名为 fileName的 .exe 可执行文件!
	if err != nil {
		panic(err)
	}

	exePath, err = filepath.Abs(exePath) //返回 exePath 的绝对路径
	if err != nil {
		panic(err)
	}

	Root = filepath.Dir(filepath.Dir(exePath)) //返回 exePath 这个文件的根目录!

	configPath := Root + initPath //当前配置文件的相对路径

	if !fileExist(configPath) {
		currentDir, _ := os.Getwd()                 //获取当前文件所在包的绝对路径
		pos := strings.LastIndex(currentDir, "src") //返回 src 这个字符串首字母在 currentDir 这个字符串中的位置
		if pos == -1 {
			panic("没有找到 /config/config.ini")
		}
		Root = currentDir[:pos]
		configPath = Root + initPath
	}
	cfgRoot = Root + "/config/"
	TemplateDir = Root + "/template/"

	Config, err = goconfig.LoadConfigFile(configPath) //加载配置文件
	if err != nil {
		panic(err)
	}

	if err = readIncludeFile(); err != nil {
		panic("读取 include files 错误:" + err.Error())
	}

	go func() {
		ch := make(chan os.Signal, 1)      //操作系统信号
		signal.Notify(ch, syscall.SIGUSR1) //将当前操作系统的信息发送到 ch 这个协程中!

		for {
			sig := <-ch //从协程中读取一个值
			switch sig {
			case syscall.SIGUSR1:
				ReloadConfigFile()
			}
		}
	}()
}

// fileExist 检查文件或目录是否存在
// fileName 指定的文件或目录存在则返回 true，否则返回 false
func fileExist(fileName string) bool {
	_, err := os.Stat(fileName)
	return err == nil || os.IsExist(err)
}

// 读取配置文件中 include_files 这个配置项的具体内容
func readIncludeFile() error {
	includeFile := Config.MustValue("include_files", "path", "")
	if includeFile != "" {
		includeFiles := strings.Split(includeFile, ",")

		list := make([]string, len(includeFiles))
		for i, v := range includeFiles {
			list[i] = cfgRoot + v
		}
		return Config.AppendFiles(list...)
	}
	return nil
}

// 重新加载配置文件
func ReloadConfigFile() {
	var err error
	configPath := Root + initPath
	Config, err = goconfig.LoadConfigFile(configPath)
	if err != nil {
		fmt.Println("重新读取配置文件错误:", err)
		return
	}
	if err = readIncludeFile(); err != nil {
		fmt.Println("重新读取 include files 错误:", err)
		return
	}
	fmt.Println("重新读取配置文件成功!")
}
